home *** CD-ROM | disk | FTP | other *** search
/ Aminet 1 (Walnut Creek) / Aminet - June 1993 [Walnut Creek].iso / usenet / sources / volume90 / audio / chaterbx / part02 / 8svx.c next >
C/C++ Source or Header  |  1990-01-17  |  8KB  |  332 lines

  1. /* quasi-minimal IFF 8SVX sample file loader for Karl's Audio Stuff
  2.  * by Karl Lehenbauer, based originally on public domain IFF code from
  3.  * Electronic Arts
  4.  * rewritten 2/25/88 KEL to support chaining of samples through a
  5.  * central sample store and to support music (it's now carrying
  6.  * around octave and one-shot info)
  7.  
  8.  *
  9.  * this version for the sound effect player has had the octave stuff
  10.  * hacked back out but the central sample store is still there
  11.  *
  12.  */
  13.  
  14. #include <exec/types.h>
  15. #include <functions.h>
  16. #include <exec/memory.h>
  17. #include <exec/nodes.h>
  18. #include <exec/lists.h>
  19. #include <stdio.h>
  20. #include <fcntl.h>
  21. #include "assert.h"
  22.  
  23. #include "iff.h"
  24. #include "8svx.h"
  25.  
  26. #include "sample.h"
  27.  
  28. struct List SampleStore;
  29. struct List *SampleList = &SampleStore;
  30.  
  31. /* this is a global variable that is set by Load8SVX to indicate whether
  32.  * it found the sample in memory already or not.  When we're playing
  33.  * sounds for the timer and noload is selected, it's a good thing to know
  34.  * and we already return a value (bleah, C is a bit restrictive in this
  35.  * case)
  36.  */
  37. int sample_was_in_cache;
  38.  
  39. char *SamplePath = "ChatterBox:";
  40.  
  41. void UnloadAllSamples()
  42. {
  43. #ifdef DEBUG
  44.     fprintf(stderr,"UnloadAllSamples cleanup routine executing\n");
  45. #endif
  46.     while (SampleList->lh_TailPred != SampleList)
  47.     {
  48.         UnloadSampleAt(SampleList->lh_Head);
  49.     }
  50. #ifdef DEBUG
  51.     fprintf(stderr,"UnloadAllSamples cleanup routine complete\n");
  52. #endif
  53. }
  54.  
  55.  
  56. Init8SVX()
  57. {
  58.     NewList(SampleList);
  59.     add_cleanup(UnloadAllSamples);
  60. }
  61.  
  62. Sample *Load8SVX(fname)
  63. char *fname;
  64. {
  65.     int iffile;
  66.     ChunkHeader chunkhead;
  67.     Voice8Header voicehead;
  68.     LONG samplebytes, fibbytes;
  69.     LONG formtype;
  70.     char *sampbufp, *fibbufp;
  71.     register Sample *samptr;
  72.     LONG headsize;
  73.     short flags = 0;
  74.     char fnamebuf[256];
  75.  
  76.     assert(sizeof(chunkhead) == 8);
  77.  
  78. #ifndef NOAUDIT
  79.     if (SampleList->lh_Head == (struct Node *)NULL)
  80.         panic("called Load8SVX without calling Init8SVX\n");
  81. #endif
  82.  
  83. #ifdef DEBUG
  84.     printf("checking sample store for %s - ",fname);
  85. #endif
  86.     if ((samptr = (Sample *)FindName(SampleList, fname)) != NULL)
  87.     {
  88. #ifdef DEBUG
  89.         printf("request for %s satisfied from sample store\n",fname);
  90. #endif
  91.         sample_was_in_cache = YES;
  92.         return(samptr);
  93.     }
  94.  
  95.     sample_was_in_cache = NO;
  96.  
  97. #ifdef DEBUG
  98.     printf("didn't find it\n");
  99. #endif
  100.  
  101.     sprintf(fnamebuf,"%s%s",SamplePath,fname);
  102. #ifdef DEBUG
  103.     printf("looking for IFF file, name of %s\n",fnamebuf);
  104.     fflush(stdout);
  105. #endif
  106.     if ((iffile = OpenIFF(fnamebuf, ID_8SVX)) < 0)
  107.     {
  108.         fprintf(stderr,"Load8SVX: can't open IFF sample file %s\n",fnamebuf);
  109.         return((Sample *)NULL);
  110.     }
  111.  
  112.     if ((headsize = chunkuntil(iffile,ID_VHDR)) == -1)
  113.     {
  114.         fputs("Load8SVX: IFF 8SVX VHDR chunk search failed\n",stderr);
  115.         return((Sample *)NULL);
  116.     }
  117.  
  118.     if (!readchunk(iffile,&voicehead,headsize))
  119.     {
  120.         fputs("Load8SVX: read of IFF VHDR chunk failed\n",stderr);
  121.         return((Sample *)NULL);
  122.     }
  123. #ifdef DEBUG
  124.     DumpVoiceHead(&voicehead);
  125. #endif
  126.  
  127.     if ((samplebytes = chunkuntil(iffile,ID_BODY)) < 0)
  128.     {
  129.         fputs("Load8SVX: IFF 8SVX BODY chunk search failed\n",stderr);
  130.         return((Sample *)NULL);
  131.     }
  132.  
  133.     if (voicehead.sCompression == sCmpFibDelta)
  134.     {
  135. #ifdef DEBUG
  136.         fprintf(stderr,"Load8SVX: sample uses Fibonacci Delta Encoding\n");
  137. #endif
  138.         fibbytes = samplebytes;
  139.         samplebytes = (fibbytes - 2) * 2;
  140.     }
  141.  
  142.     if ((sampbufp = (char *)AllocMem(samplebytes,MEMF_FAST)) == (char *)NULL)
  143.     {
  144.         if ((sampbufp = (char *)AllocMem(samplebytes,MEMF_CHIP)) == (char *)NULL)
  145.         {
  146.             fputs("Load8SVX: unable to allocate memory for waveform\n",stderr);
  147.             return((Sample *)NULL);
  148.         }
  149.         else
  150.             flags = SAMPLE_ALLOCATED_IN_CHIP_RAM;
  151.  
  152.     }
  153.     else
  154.         flags = SAMPLE_ALLOCATED_IN_FAST_RAM;
  155.  
  156.     if (voicehead.sCompression == sCmpFibDelta)
  157.     {
  158.  
  159.         /* load the delta compressed data into the back half of the sample
  160.          * buffer just allocated.  We will decompress the data into the 
  161.          * same sample memory, without overwriting the compressed data.
  162.          * It'll work.  Trust me, I know what I'm doing.
  163.          */
  164.  
  165.         fibbufp = &sampbufp[samplebytes / 2];
  166.  
  167.         if (!readchunk(iffile,fibbufp,fibbytes))
  168.         {
  169.             fputs("Read of fib sample data failed!\n",stderr);
  170.             FreeMem(sampbufp,samplebytes);
  171.             return((Sample *)NULL);
  172.         }
  173.         FibUnpack(fibbufp+2,fibbytes-2,sampbufp,fibbufp[1]);
  174.     }
  175.     else if (!readchunk(iffile,sampbufp,samplebytes))
  176.     {
  177.         fputs("Read of sample data failed!\n",stderr);
  178.         FreeMem(sampbufp,samplebytes);
  179.         return((Sample *)NULL);
  180.     }
  181.  
  182.     close(iffile);
  183.  
  184.     if ((samptr = (Sample *)AllocMem(sizeof(Sample),0L)) == (Sample *)NULL)
  185.     {
  186.        fputs("Load8SVX: unable to allocate memory for Sample structure\n",stderr);
  187.        FreeMem(sampbufp,samplebytes);
  188.        return((Sample *)NULL);
  189.     }
  190.  
  191.     /* allocate memory for sample name */
  192.     if ((samptr->node.ln_Name = (char *)AllocMem(strlen(fname) + 1,0)) == (char *)NULL)
  193.     {
  194.         fputs("Load8SVX: unable to allocate memory for Sample name\n",stderr);
  195.         FreeMem(sampbufp,samplebytes);
  196.         FreeMem(samptr,sizeof(Sample));
  197.         return((Sample *)NULL);
  198.     }
  199.  
  200.     /* structure copy in Voice8Header info */
  201.     samptr->sampleheader = voicehead;
  202.  
  203.     /* set up pointer to sample data and store length */
  204.     if (flags & SAMPLE_ALLOCATED_IN_FAST_RAM)
  205.     {
  206.         samptr->fastsampledata = sampbufp;
  207.         samptr->sampledata = NULL;
  208.     }
  209.     else if (flags & SAMPLE_ALLOCATED_IN_CHIP_RAM)
  210.     {
  211.         samptr->fastsampledata = NULL;
  212.         samptr->sampledata = sampbufp;
  213.     }
  214.     samptr->samplebytes = samplebytes;
  215.  
  216.     /* copy in the voice name */
  217.     strcpy(samptr->node.ln_Name,fname);
  218.  
  219.     /* ...and set up the flags */
  220.     samptr->sample_flags = flags;
  221.  
  222.     /* set the number of current "users" of the sample in chip RAM to zero */
  223.     samptr->chip_use_count = 0;
  224.  
  225.     /* initialize the rest of the node fields */
  226.     samptr->node.ln_Type = samptr->node.ln_Pri = 0;
  227.  
  228.     /* stick this new sample onto the end of the sample list */
  229.     AddTail(SampleList,&samptr->node);
  230.  
  231. #ifndef NOAUDIT
  232.     samptr->magic = SAMPLE_MAGIC;
  233. #endif
  234.  
  235. #ifdef DEBUG
  236.     fprintf(stderr,"Load8SVX: waveform bytes %ld, samples/second %d\n",samplebytes,voicehead.samplesPerSec);
  237.     fprintf(stderr,"Load8SVX: samptr %lx, sampledata %lx\n",samptr,sampbufp);
  238. #endif
  239.     return(samptr);
  240. }
  241.  
  242. /* FibUnpack - unpack Fibonacci Delta Compressed audio sample
  243.  *                see IFF file formats in the ROM Kernel Exec manual
  244.  *                or on one of the Fred Fish disks
  245.  */
  246.  
  247. char FibToDelta[16] = {-34,-21,-13,-8,-5,-3,-2,-1,0,1,2,3,5,8,13,21};
  248.  
  249. FibUnpack(inp,n,outp,val)
  250. char *inp, *outp;
  251. long n;
  252. char val;
  253. {
  254.     register char pair;
  255. #ifdef DEBUG
  256.     fprintf(stderr,"FibUnpack: inp %lx, n %ld, outp %lx, val %d\n",inp,n,outp,val);
  257. #endif
  258.     while (n--)
  259.     {
  260.         pair = *inp++;                /* get a pair of compressed samples */
  261.         val += FibToDelta[(pair >> 4) & 0xf]; /* uncompress first sample */
  262.         *outp++ = val;
  263.         val += FibToDelta[pair & 0xf];        /* uncompress second sample */
  264.         *outp++ = val;
  265.     }
  266. }
  267.  
  268. /* unload sample at address */
  269. UnloadSampleAt(samptr)
  270. Sample *samptr;
  271. {
  272.     ASSERT_SAMPLE_MAGIC(samptr);
  273.  
  274. #ifdef DEBUG
  275.     printf("UnloadSampleAt: Unloading Sample %s\n",samptr->node.ln_Name);
  276. #endif
  277.  
  278.     /* remove the sample from the sample list */
  279.     Remove(&samptr->node);
  280.  
  281.     /* free the space allocated for the sample's name */
  282.     FreeMem(samptr->node.ln_Name,strlen(samptr->node.ln_Name)+1);
  283.  
  284.     /* free the sample data itself */
  285.     if (samptr->sample_flags & SAMPLE_ALLOCATED_IN_CHIP_RAM)
  286.     {
  287.         FreeMem(samptr->sampledata,samptr->samplebytes);
  288.     }
  289.     else
  290.     {
  291.         assert(samptr->sample_flags & SAMPLE_ALLOCATED_IN_FAST_RAM);
  292.         FreeMem(samptr->fastsampledata,samptr->samplebytes);
  293.     }
  294. #ifndef NOAUDIT
  295.     samptr->magic = 0;
  296. #endif
  297.     samptr->sample_flags = 0;
  298.  
  299.     /* free the sample structure */
  300.     FreeMem(samptr,sizeof(Sample));
  301. }
  302.  
  303. UnloadSample(name)
  304. char *name;
  305. {
  306.     Sample *samptr;
  307.  
  308. #ifdef DEBUG
  309.     printf("UnloadSample(%s)\n",name);
  310. #endif
  311.     
  312.     if ((samptr = (Sample *)FindName(SampleList,name)) != NULL)
  313.         UnloadSampleAt(samptr);
  314.     else
  315.         fprintf(stderr,"couldn't find sample %s to unload it\n",name);
  316. }
  317.  
  318. #ifdef DEBUG
  319. DumpVoiceHead(vptr)
  320. Voice8Header *vptr;
  321. {
  322.     printf("oneShotHiSamples %d, repeatHiSamples %d\n",
  323.         vptr->oneShotHiSamples, vptr->repeatHiSamples);
  324.     printf("samplesPerHiCycle %ld, samplesPerSec %d\n",
  325.         vptr->samplesPerHiCycle, vptr->samplesPerSec);
  326.     printf("ctOctave %d, sCompression %d, volume %d\n",
  327.         vptr->ctOctave, vptr->sCompression, vptr->volume);
  328. }
  329. #endif
  330.  
  331. /* end of 8svx.c */
  332.